<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>改变函数内部this的指向</title>
</head>

<body>
  <button>按钮</button>
  <script>
    // ---------------------------call方法------------------------
    // function fn(x, y) {
    //   console.log(this);
    //   console.log(x + y);
    // }
    // var obj = {
    //   uname: 'zs'
    // }
    // // fn.call(); //调用函数
    // fn.call(obj, 1, 2) //改变this的指向 
    // // call的主要作用的可以实现继承
    // function Fa(uname, age) {
    //   this.uname = uname;
    //   this.age = age;
    // }
    // function Son(uname, age, score) {
    //   Fa.call(this, uname, age); //this --> 指向实例对象xm
    //   this.score = score;
    // }
    // var xm = new Son('小明', 12, 99);
    // console.log(xm);

    // ---------------------------apply方法------------------------
    // function fn(arr) {
    //   console.log(this);
    //   console.log(arr); // 'pink' 打印出字符串
    // }
    // var obj = {
    //   uname: 'zs'
    // }
    // fn.apply() //调用函数
    // fn.apply(obj, ['pink']) //改变this的指向
    // // 他的参数必须是数组（伪数组）
    // // apply主要应用 比如我们可以利用apply借助于数学内置对象求最大值
    // var arr = [1, 5, 89, 11, 56, 30];
    // var max = Math.max.apply(Math, arr); //apply会把数组转化
    // console.log(max);

    // ---------------------------bind方法------------------------
    // function fn(arr) {
    //   console.log(this);
    // }
    // var obj = {
    //   uname: 'zs'
    // }
    // // fn.bind(obj)  //没有输出 bind()不会调用原来的函数
    // var f = fn.bind(obj); // 返回了原函数改变this指向之后产生的新函数
    // f(); // {uname: "zs"} 可以改变this的指向
    // // 如果有的函数我们不需要立即调用 但是又想改变函数内部this的指向 此时用bind
    // 例：有个一按钮点击之后禁用 3秒后开启
    var btn = document.querySelector('button')
    btn.onclick = function () {
      this.disabled = true;
      setTimeout(function () {
        this.disabled = false; //定时器里this指向的是 window
      }.bind(this), 3000) // 这个this是btn 用bind改变里面this的指向 并且不立即调用 这里用call和apply都不行 他们会立即调用函数
    }

    // ---------------------------区别------------------------
    function fn(n, m, i) {
      console.log(this, n, m, i);
    }
    var obj = {
      uname: '张三'
    }
    fn.call(obj, 9, 10, 11) // {uname: "张三"} 9 10 11
    fn.apply(obj, [8, 7, 6]) // {uname: "张三"} 8 7 6
    var test = fn.bind(obj, 1, 3, 6) // {uname: "张三"} 1 3 6
    test();

    // call 和 apply 会调用函数，并且改变函数内部this的指向
    // call 和 apply 传递的参数不一样 call传递参数aru1,aru2...形式 apply是数组形式[aru]
    // bind 不会调用函数 可以改变函数内部this的指向

  </script>
</body>

</html>